package com.lnsoft.cac.server.handle.codec.frameMessage;

import com.lnsoft.cac.server.util.Arrays16;
import com.lnsoft.cac.server.util.CRC16;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import lombok.extern.slf4j.Slf4j;

import java.math.BigDecimal;

@Slf4j
public class FrameFactory {


    //  心跳发送帧
    public static ByteBuf heartSendFrame(byte[] clientID, int frameSerialNum) throws Exception {
        int currentTimeSeconds = currentTimeSeconds();
        ByteBuf message = Unpooled.buffer();
        message.writeIntLE(currentTimeSeconds);
        return frame(clientID, (byte) 0x01, (byte) 0x01, frameSerialNum, message);
    }

    //  心跳确认帧
    public static ByteBuf heartCfmFrame(byte[] clientID, int frameSerialNum) throws Exception {
        int currentTimeSeconds = currentTimeSeconds();
        ByteBuf message = Unpooled.buffer();
        message.writeByte(0x000000FF);  //  数据发送状态：成功
        message.writeIntLE(currentTimeSeconds);
        return frame(clientID, (byte) 0x02, (byte) 0x01, frameSerialNum, message);
    }

    //  当前时间（世纪秒）
    public static int currentTimeSeconds() {
        return BigDecimal.valueOf(System.currentTimeMillis() / 1000).setScale(0, BigDecimal.ROUND_HALF_UP).intValue();
    }


    //  根据入参（电压监测仪ID、帧类型、报文类型、帧序列号、报文内容）组装可以发送的报文帧
    private static ByteBuf frame(byte[] clientID,int frameType,int messageType,int frameSerialNum,ByteBuf message) throws Exception {
        if (clientID.length != 17) {
            throw new Exception("终端ID长度不正确！");
        }
        if (frameSerialNum < 0 || frameSerialNum > 256) {
            throw new Exception("帧序列号异常！");
        }
        //  构造ByteBuf并根据帧格式填入相应数据
        ByteBuf byteBuf = Unpooled.buffer();
        byteBuf.writeShortLE((short) 0x5AA5).writeShortLE(message.writerIndex()).writeBytes(clientID).writeByte(frameType).writeByte(messageType).writeByte(frameSerialNum)
                .writeBytes(message).writeShort((short) 0x0000).writeByte((byte) 0x96);
        byte[] tempBytes = new byte[22 + message.writerIndex()];
        byteBuf.getBytes(2, tempBytes);
        //  修改校验码
        int cs = CRC16.GetCRC16(tempBytes, tempBytes.length);
        byteBuf.setShortLE(24 + message.writerIndex(), (short) cs);
        return byteBuf;
    }

    //数据请求报文
    public static ByteBuf dataFrame(byte[] clientID, int frameSerialNum) throws Exception{
        int currentTimeSeconds = currentTimeSeconds();
        ByteBuf msgBody = Unpooled.buffer();
       // msgBody.writerunsingedbyte
        return frame(clientID, (byte) 0x05, (byte) 0xA1, frameSerialNum, msgBody);
    }


    //  监测数据报文-电压数据-发送报文
    public static ByteBuf vol_SendFrame(byte[] clientID, int frameSerialNum, ByteBuf message) throws Exception {
        return frame(clientID, (byte) 0x03, (byte) 0x04, frameSerialNum, message);
    }

    //  监测数据报文-电压数据-确认报文
    public static ByteBuf vol_CfmFrame(byte[] clientID, int frameSerialNum, ByteBuf message) throws Exception {
        return frame(clientID, (byte) 0x04, (byte) 0x04, frameSerialNum, message);
    }

    //  监测数据报文-电压日统计数据-发送报文
    public static ByteBuf vol_Day_SendFrame(byte[] clientID, int frameSerialNum, ByteBuf message) throws Exception {
        return frame(clientID, (byte) 0x03, (byte) 0x05, frameSerialNum, message);
    }

    //  监测数据报文-电压日统计数据-确认报文
    public static ByteBuf vol_Day_CfmFrame(byte[] clientID, int frameSerialNum, ByteBuf message) throws Exception {
        return frame(clientID, (byte) 0x04, (byte) 0x05, frameSerialNum, message);
    }

    //  监测数据报文-电压月统计数据-发送报文
    public static ByteBuf vol_Mon_SendFrame(byte[] clientID, int frameSerialNum, ByteBuf message) throws Exception {
        return frame(clientID, (byte) 0x03, (byte) 0x06, frameSerialNum, message);
    }

    //  监测数据报文-电压月统计数据-确认报文
    public static ByteBuf vol_Mon_CfmFrame(byte[] clientID, int frameSerialNum, ByteBuf message) throws Exception {
        return frame(clientID, (byte) 0x04, (byte) 0x06, frameSerialNum, message);
    }

    //  流量数据报文-发送报文
    public static ByteBuf flow_SendFrame(byte[] clientID, int frameSerialNum, ByteBuf message) throws Exception {
        return frame(clientID, (byte) 0x09, (byte) 0xC1, frameSerialNum, message);
    }

    //  流量数据报文-确认报文
    public static ByteBuf flow_CfmFrame(byte[] clientID, int frameSerialNum, ByteBuf message) throws Exception {
        return frame(clientID, (byte) 0x10, (byte) 0xC1, frameSerialNum, message);
    }

    //  事件信息报文-发送报文
    public static ByteBuf event_SendFrame(byte[] clientID, int frameSerialNum, ByteBuf message) throws Exception {
        return frame(clientID, (byte) 0x11, (byte) 0xC4, frameSerialNum, message);
    }

    //  事件信息报文-确认报文
    public static ByteBuf event_CfmFrame(byte[] clientID, int frameSerialNum, ByteBuf message) throws Exception {
        return frame(clientID, (byte) 0x12, (byte) 0xC4, frameSerialNum, message);
    }

    //  数据请求报文-发送报文
    public static ByteBuf request_SendFrame(byte[] clientID, int frameSerialNum, ByteBuf message) throws Exception {
        return frame(clientID, (byte) 0x05, (byte) 0xA1, frameSerialNum, message);
    }

    //  数据请求报文-确认报文
    public static ByteBuf request_CfmFrame(byte[] clientID, int frameSerialNum, ByteBuf message) throws Exception {
        return frame(clientID, (byte) 0x06, (byte) 0xA1, frameSerialNum, message);
    }

    //  配置/状态交互数据报文-装置时间-发送报文
    public static ByteBuf cfg_time_SendFrame(byte[] clientID, int frameSerialNum, ByteBuf message) throws Exception {
        return frame(clientID, (byte) 0x07, (byte) 0xA4, frameSerialNum, message);
    }

    //  配置/状态交互数据报文-装置时间-确认报文
    public static ByteBuf cfg_time_CfmFrame(byte[] clientID, int frameSerialNum, ByteBuf message) throws Exception {
        return frame(clientID, (byte) 0x08, (byte) 0xA4, frameSerialNum, message);
    }

    //  配置/状态交互数据报文-装置通信参数-发送报文
    public static ByteBuf cfg_commu_SendFrame(byte[] clientID, int frameSerialNum, ByteBuf message) throws Exception {
        return frame(clientID, (byte) 0x07, (byte) 0xA6, frameSerialNum, message);
    }

    //  配置/状态交互数据报文-装置通信参数-确认报文
    public static ByteBuf cfg_commu_CfmFrame(byte[] clientID, int frameSerialNum, ByteBuf message) throws Exception {
        return frame(clientID, (byte) 0x08, (byte) 0xA6, frameSerialNum, message);
    }

    //  配置/状态交互数据报文-监测点参数-发送报文
    public static ByteBuf cfg_measure_point_SendFrame(byte[] clientID, int frameSerialNum, ByteBuf message) throws Exception {
        return frame(clientID, (byte) 0x07, (byte) 0xA7, frameSerialNum, message);
    }

    //  配置/状态交互数据报文-监测点参数-确认报文
    public static ByteBuf cfg_measure_point_CfgFrame(byte[] clientID, int frameSerialNum, ByteBuf message) throws Exception {
        return frame(clientID, (byte) 0x08, (byte) 0xA7, frameSerialNum, message);
    }

    //  配置/状态交互数据报文-装置事件参数-发送报文
    public static ByteBuf cfg_event_arg_SendFrame(byte[] clientID, int frameSerialNum, ByteBuf message) throws Exception {
        return frame(clientID, (byte) 0x07, (byte) 0xA8, frameSerialNum, message);
    }

    //  配置/状态交互数据报文-装置事件参数-确认报文
    public static ByteBuf cfg_event_arg_CfmFrame(byte[] clientID, int frameSerialNum, ByteBuf message) throws Exception {
        return frame(clientID, (byte) 0x08, (byte) 0xA8, frameSerialNum, message);
    }

    //  配置/状态交互数据报文-装置所属CAC的信息-发送报文
    public static ByteBuf cfg_cac_sub_SendFrame(byte[] clientID, int frameSerialNum, ByteBuf message) throws Exception {
        return frame(clientID, (byte) 0x07, (byte) 0xA9, frameSerialNum, message);
    }

    //  配置/状态交互数据报文-装置所属CAC的信息-确认报文
    public static ByteBuf cfg_cac_sub_CfmFrame(byte[] clientID, int frameSerialNum, ByteBuf message) throws Exception {
        return frame(clientID, (byte) 0x08, (byte) 0xA9, frameSerialNum, message);
    }

    //  配置/状态交互数据报文-装置基本信息-发送报文
    public static ByteBuf cfg_dev_info_SendFrame(byte[] clientID, int frameSerialNum, ByteBuf message) throws Exception {
        return frame(clientID, (byte) 0x07, (byte) 0xAA, frameSerialNum, message);
    }

    //  配置/状态交互数据报文-装置基本信息-确认报文
    public static ByteBuf cfg_dev_info_CfmFrame(byte[] clientID, int frameSerialNum, ByteBuf message) throws Exception {
        return frame(clientID, (byte) 0x08, (byte) 0xAA, frameSerialNum, message);
    }

    //  配置/状态交互数据报文-装置工作状态信息查询-发送报文
    public static ByteBuf cfg_dev_status_SendFrame(byte[] clientID, int frameSerialNum, ByteBuf message) throws Exception {
        return frame(clientID, (byte) 0x07, (byte) 0xAB, frameSerialNum, message);
    }

    //  配置/状态交互数据报文-装置工作状态信息查询-确认报文
    public static ByteBuf cfg_dev_status_CfmFrame(byte[] clientID, int frameSerialNum, ByteBuf message) throws Exception {
        return frame(clientID, (byte) 0x08, (byte) 0xAB, frameSerialNum, message);
    }

    //  配置/状态交互数据报文-装置通信流量信息查询-发送报文
    public static ByteBuf cfg_dev_flow_SendFrame(byte[] clientID, int frameSerialNum, ByteBuf message) throws Exception {
        return frame(clientID, (byte) 0x07, (byte) 0xAC, frameSerialNum, message);
    }

    //  配置/状态交互数据报文-装置通信流量信息查询-确认报文
    public static ByteBuf cfg_dev_flow_CfmFrame(byte[] clientID, int frameSerialNum, ByteBuf message) throws Exception {
        return frame(clientID, (byte) 0x08, (byte) 0xAC, frameSerialNum, message);
    }

    //  配置/状态交互数据报文-装置ID查询-发送报文
    public static ByteBuf cfg_dev_id_SendFrame(byte[] clientID, int frameSerialNum, ByteBuf message) throws Exception {
        return frame(clientID, (byte) 0x07, (byte) 0xAD, frameSerialNum, message);
    }

    //  配置/状态交互数据报文-装置ID查询-确认报文
    public static ByteBuf cfg_dev_id_CfmFrame(byte[] clientID, int frameSerialNum, ByteBuf message) throws Exception {
        return frame(clientID, (byte) 0x08, (byte) 0xAD, frameSerialNum, message);
    }

    //  配置/状态交互数据报文-装置复位-发送报文
    public static ByteBuf cfg_dev_reset_SendFrame(byte[] clientID, int frameSerialNum, ByteBuf message) throws Exception {
        return frame(clientID, (byte) 0x07, (byte) 0xAE, frameSerialNum, message);
    }

    //  配置/状态交互数据报文-装置复位-确认报文
    public static ByteBuf cfg_dev_reset_CfmFrame(byte[] clientID, int frameSerialNum, ByteBuf message) throws Exception {
        return frame(clientID, (byte) 0x08, (byte) 0xAE, frameSerialNum, message);
    }

    //  配置/状态交互数据报文-装置调试命令交互-发送报文
    public static ByteBuf cfg_dev_debug_SendFrame(byte[] clientID, int frameSerialNum, ByteBuf message) throws Exception {
        return frame(clientID, (byte) 0x07, (byte) 0xAF, frameSerialNum, message);
    }

    //  配置/状态交互数据报文-装置调试命令交互-确认报文
    public static ByteBuf cfg_dev_debug_CfmFrame(byte[] clientID, int frameSerialNum, ByteBuf message) throws Exception {
        return frame(clientID, (byte) 0x08, (byte) 0xAF, frameSerialNum, message);
    }

    //  远程升级-升级启动-发送报文
    public static ByteBuf upgrade_start_SendFrame(byte[] clientID, int frameSerialNum, ByteBuf message) throws Exception {
        return frame(clientID, (byte) 0x13, (byte) 0xC7, frameSerialNum, message);
    }

    //  远程升级-升级启动-确认报文
    public static ByteBuf upgrade_start_CfmFrame(byte[] clientID, int frameSerialNum, ByteBuf message) throws Exception {
        return frame(clientID, (byte) 0x14, (byte) 0xC7, frameSerialNum, message);
    }

    //  远程升级-升级过程中-发送报文
    public static ByteBuf upgrade_proc_SendFrame(byte[] clientID, int frameSerialNum, ByteBuf message) throws Exception {
        return frame(clientID, (byte) 0x13, (byte) 0xC8, frameSerialNum, message);
    }

    //  远程升级-升级过程中-确认报文
    public static ByteBuf upgrade_proc_CfmFrame(byte[] clientID, int frameSerialNum, ByteBuf message) throws Exception {
        return frame(clientID, (byte) 0x14, (byte) 0xC8, frameSerialNum, message);
    }

    //  远程升级-升级结束-发送报文
    public static ByteBuf upgrade_end_SendFrame(byte[] clientID, int frameSerialNum, ByteBuf message) throws Exception {
        return frame(clientID, (byte) 0x13, (byte) 0xC9, frameSerialNum, message);
    }

    //  远程升级-升级结束-确认报文
    public static ByteBuf upgrade_end_CfmFrame(byte[] clientID, int frameSerialNum, ByteBuf message) throws Exception {
        return frame(clientID, (byte) 0x14, (byte) 0xC9, frameSerialNum, message);
    }

    //  监测数据报-电压数据报
    public static ByteBuf voltageMsg() {
        ByteBuf bf = Unpooled.buffer();
        double random = Math.random();
        //  随机写入一个监测点号
        bf.writeByte((int) (random * 255));

        int listLength = (int) (random * 12);
        bf.writeByte(listLength);

        int currentTime = currentTimeSeconds();
        log.info("************");
        log.info(Integer.toString(currentTime));
        //  写入多组 电压数据
        for (int i = 0; i < listLength; i++) {
            bf.writeIntLE(currentTime + i * 600);
            bf.writeInt((int) (random * 500000));
        }
        return bf;
    }


}
